﻿using System;
using System.Collections;
using System.Xml;
using System.Text;
using InfoJetSoft.Service.Entity;
using InfoJetSoft.Service.Util;

namespace InfoJetSoft.Service.Worker
{
	
	class XSNManifestMenuParseWorker
	{
		
		public static void  parseMemu(Manifest manifest)
		{
			XmlElement root = manifest.Doc.DocumentElement;
			string xsfPrefix = manifest.XsfPrefix;
			
			ArrayList viewList = manifest.ViewList;
			foreach (View view in viewList)
			{
				Menu contextMenu = new Menu();
				contextMenu.Type = JetConstant.MNU_MENU;
				contextMenu.Id = JetConstant.CONTEXT_MENU_ID + ".";
				
				ArrayList menuList = new ArrayList();
				
				StringBuilder filterBuffer = new StringBuilder();
				filterBuffer.Append("//");
				filterBuffer.Append(NamespaceUtil.toFullName(xsfPrefix, "view"));
				filterBuffer.Append("[@name='" + view.Name + "']");
				filterBuffer.Append("/");
				filterBuffer.Append(NamespaceUtil.toFullName(xsfPrefix, "menuArea"));
				filterBuffer.Append("[@name='msoStructuralEditingContextMenu']");
				
				XmlElement contextMenuElement = (XmlElement) DOMUtil.selectANode(root, filterBuffer.ToString(), manifest.NsResolver);
				if (contextMenuElement != null)
				{
					XmlNodeList menuXmlNodeList = contextMenuElement.ChildNodes;
					int index = 0;
					foreach (XmlNode menuNode in contextMenuElement.ChildNodes)
					{
						if (menuNode is XmlElement)
						{
							XmlElement element = (XmlElement) menuNode;
							//CID 0022 //2008.06.23 //Begin
							//Menu的定义总是输出的,因为他们不包含动作,如果Menu定义中的Button都在只读视图里不显示,那么应该隐藏这个Menu.
							//但是目前处理太复杂,暂时不考虑,而且如果不手工修改,是无法在InfoPath Design Mode中定义出Menu的.
							//CID 0022 //2008.06.23 //End
							if (element.Name.Equals(NamespaceUtil.toFullName(xsfPrefix, "menu")))
							{
								parseMenuElement(manifest, element, menuList, index + ".");
								index++;
							}
							else if (element.Name.Equals(NamespaceUtil.toFullName(xsfPrefix, "button")))
							{
								//如果View不是Readonly的,输出view中定义的menu.否则如果是Readonly,则不输出,只输出切换view的menu条目.
								if( (!view.IsReadonly) || (view.IsReadonly && MenuUtil.isReadonlyMenuButton( element ))  ) //CID 0022 //2008.06.23 //if
								{
									if( tryParseButtonElement(manifest, element, menuList, index + ".") )
									{
										index ++;
									}
								}
							}
						}
					}
				}

				
				if (menuList.Count > 0)
				{
					Menu sepItem = new Menu();
					sepItem.Type = JetConstant.MNU_SEPARATOR;
					sepItem.Action = JetConstant.MNU_ACT_NONE;
					sepItem.Id = menuList.Count + ".";
					menuList.Add(sepItem);
				}
				
				if( !ConfigUtil.HideSwitchViewMenus() )	//CID 0054 //2008.07.18 //if
				{
					int menuSize = menuList.Count;
					ArrayList showMenuItemViewList = new ArrayList();
					foreach( View curView in viewList )
					{
						if( curView.ShowMenuItem )
						{
							showMenuItemViewList.Add( curView );
						}
					}
					for (int i = 0; i < showMenuItemViewList.Count; i++)
					{
						View curView = (View) showMenuItemViewList[ i ];
						Menu viewItem = new Menu();
						viewItem.Type = JetConstant.MNU_BUTTON;
						viewItem.Caption = curView.Caption;
						viewItem.Id = (i + menuSize) + ".";
						viewItem.Action = JetConstant.MNU_ACT_SWITCHVIEW;
						viewItem.Component = curView.Id;
						viewItem.XmlToEdit = "";
						menuList.Add(viewItem);
					}
				}

				//如果上一个菜单项是分隔线,不再添加分隔线;如果不是就添加一个.
				if (menuList.Count > 0)
				{
					Menu lastMenu = (Menu)menuList[ menuList.Count - 1 ];
					if( !lastMenu.Type.Equals( JetConstant.MNU_SEPARATOR ) )
					{
						Menu sepItem = new Menu();
						sepItem.Type = JetConstant.MNU_SEPARATOR;
						sepItem.Action = JetConstant.MNU_ACT_NONE;
						sepItem.Id = menuList.Count + ".";
						menuList.Add(sepItem);
					}
				}
				
				//如果不需要隐藏DEFMenu.
				if( !ConfigUtil.HideDEFMenu() )
				{
					Menu noErrFrmtItem = new Menu();
					noErrFrmtItem.Type = JetConstant.MNU_BUTTON;
					noErrFrmtItem.Caption = "Disable Error Formatting";
					noErrFrmtItem.Id = menuList.Count + ".";
					noErrFrmtItem.Action = JetConstant.MNU_ACT_NOERRORFORMATTING;
					noErrFrmtItem.Component = "";
					noErrFrmtItem.XmlToEdit = "";
					menuList.Add(noErrFrmtItem);
				}

				//添加Printable Version菜单项.
				if( !ConfigUtil.HidePrintableVersionMenu() )
				{
					Menu printableVersionItem = new Menu();
					printableVersionItem.Type = JetConstant.MNU_BUTTON;
					printableVersionItem.Caption = ConfigUtil.PrintableVersionMenuText();
					printableVersionItem.Id = menuList.Count + ".";
					printableVersionItem.Action = JetConstant.MNU_ACT_PRINTABLEVERSION;
					printableVersionItem.Component = "";
					printableVersionItem.XmlToEdit = "";
					menuList.Add(printableVersionItem);
				}

				//检查最后一个菜单是否是SEPARATOR,如果是删除.
				if(menuList.Count > 0)
				{
					Menu lastMenu = (Menu)menuList[ menuList.Count - 1 ];
					if( lastMenu.Type.Equals( JetConstant.MNU_SEPARATOR ) )
					{
						menuList.Remove( lastMenu );
					}
				}
				
				contextMenu.SubMenuList = menuList;
				//CID 0284 //2009.05.10 //Begin
				view.ContextMenu = contextMenu;
				//CID 0284 //2009.05.10 //End
			}
		}
		
		private static void parseMenuElement(Manifest manifest, XmlElement menuElement, ArrayList menuList, string id)
		{
			string xsfPrefix = manifest.XsfPrefix;
			
			string caption = menuElement.GetAttribute("caption");
			if (caption.Length <= 0)
			{
				throw new InfoJetException("menu no caption", "XMPW01");
			}
			Menu menu = new Menu();
			menu.Type = JetConstant.MNU_MENU;
			menu.Caption = caption;
			menu.Id = id;
			menuList.Add(menu);
			
			ArrayList subMenuList = new ArrayList();
			
			int index = 0;
			foreach (XmlNode menXmlNode in menuElement.ChildNodes)
			{
				if (menXmlNode is XmlElement)
				{
					XmlElement element = (XmlElement) menXmlNode;
					if (element.Name.Equals(NamespaceUtil.toFullName(xsfPrefix, "menu")))
					{
						parseMenuElement(manifest, element, subMenuList, id + index + ".");
						index++;
					}
					else if (element.Name.Equals(NamespaceUtil.toFullName(xsfPrefix, "button")))
					{
						if( tryParseButtonElement(manifest, element, subMenuList, id + index + ".") )
						{
							index++;
						}
					}
				}
			}
			
			menu.SubMenuList = subMenuList;
		}
		
		private static bool tryParseButtonElement(Manifest manifest, XmlElement buttonElement, ArrayList menuList, string id)
		{
			string caption = buttonElement.GetAttribute("caption");
			if (caption.Length <= 0)
			{
				throw new InfoJetException("button no caption", "XMPW02");
			}
			string xmlToEdit = buttonElement.GetAttribute("xmlToEdit");
			if (xmlToEdit.Length <= 0)
			{
				throw new InfoJetException("button no xmlToEdit", "XMPW03");
			}
			string action = buttonElement.GetAttribute("action");
			if (action.Length <= 0)
			{
				throw new InfoJetException("button no action", "XMPW04");
			}
			StringTokenizer actionTokenizer = new StringTokenizer(action, "::");
			if (actionTokenizer.Count != 2)
			{
				throw new InfoJetException("button action invalid format", "XMPW05");
			}
			string component = actionTokenizer.NextToken();
			action = actionTokenizer.NextToken();
			Menu button = new Menu();
			button.Type = JetConstant.MNU_BUTTON;
			button.Action = action;
			button.Caption = caption;
			button.Component = component;
			button.XmlToEdit = xmlToEdit;
			button.Id = id;
			if( button.Component.Equals( JetConstant.CMP_xFileAttachment ) )
			{
				button.Caption = button.Caption.Replace( "&", "" );
			}
			
			return addButton2MenuList(manifest, menuList, button);
		}
		
		private static bool addButton2MenuList(Manifest manifest, ArrayList menuList, Menu button)
		{
			XmlToEdit buttonXmlToEdit = null;
			ArrayList xmlToEditList = manifest.XmlToEditList;
			for (int i = 0; i < xmlToEditList.Count; i++)
			{
				XmlToEdit xmlToEdit = (XmlToEdit) xmlToEditList[i];
				if (xmlToEdit.Name.Equals(button.XmlToEdit))
				{
					button.XmlToEditItem = xmlToEdit.Item;
					buttonXmlToEdit = xmlToEdit;
					break;
				}
			}
			if (buttonXmlToEdit == null)
			{
				return false;
			}
			
			foreach (Menu menu in menuList)
			{
				if (menu.Action != null && menu.Component != null && menu.XmlToEditItem != null)
				{
					if (menu.Action.Equals(button.Action) && menu.Component.Equals(button.Component) && menu.XmlToEditItem.Equals(button.XmlToEditItem))
					{
						if (buttonXmlToEdit.ViewContext == null || buttonXmlToEdit.ViewContext.Length <= 0)
						{
							// Master/Detial
						}
						else
						{
							return false;
						}
					}
				}
			}
			menuList.Add(button);
			return true;
		}
	}
}